#pragma once

#include <cstdio>
#include <cstdarg>
#include <assert.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <cassert>
#include <time.h>
#include <cstdlib>

#define DEBUG 0 
#define NOTICE 1
#define WARNING 2
#define FATAL 3

#define LOGFILE "tcp_server_log"

const char* log_level[] = {"DEBUG", "NOTICE", "WARNING", "FATAL"};

class Log
{
public:
    Log()
        : logfd_(-1)
    {}

    void launch() // 启动
    {
        umask(0);
        logfd_ = open(LOGFILE, O_WRONLY | O_CREAT | O_APPEND, 0666);
        assert(logfd_ != -1);
        dup2(logfd_, 1);
        dup2(logfd_, 2);
    }

    ~Log()
    {
        if (logfd_ != -1)
        {
            fsync(logfd_);
            close(logfd_);
        }
    }
private:
    int logfd_; // 日志文件
};

int g_logfd = -1;

void logMsg(int level, const char* format, ...)
{
    assert(level >= DEBUG);
    assert(level <= FATAL);

    char *name = getenv("USER");

    char logInfo[1024];
    va_list ap; // ap -> char*
    // 根据这个参数定位到可变部分的参数
    va_start(ap, format);

    vsnprintf(logInfo, sizeof(logInfo)-1, format, ap);

    va_end(ap); // ap = NULL

    // umask(0);
    // int log_fd = open(LOGFILE, O_WRONLY | O_CREAT | O_APPEND, 0666);
    // assert(log_fd > 0);

    FILE *out = (level == FATAL) ? stderr : stdout;

    // 将格式化的内容写到哪个文件/流里面
    fprintf(out, "%s | %u | %s | %s\n", \
        log_level[level], \
        (unsigned int)time(nullptr),\
        name == nullptr ? "unknow":name,\
        logInfo);
    
    fflush(out);   // 将 C 缓冲区中的数据刷新到 os
    fsync(fileno(out)); // os 的数据刷新到磁盘中
}
